﻿using UnityEngine;
using System.Collections.Generic;
using System.IO;
#if UNITY_EDITOR
using UnityEditor;
#endif

public class LevelCreator : MonoBehaviour
{
	public GameObject wallParent;
	public GameObject tileParent;
	public GameObject doorParent;

	public Texture2D wallToCreate;

	public void CreateWallImage()
	{
		wallToCreate.Resize(2024, 2024);
		ClearTexture(wallToCreate);

		wallParent.SetActive(true);
		SpriteRenderer[] wallPieces = wallParent.GetComponentsInChildren<SpriteRenderer>();
		foreach (SpriteRenderer wall in wallPieces)
		{
			float sceneX = wall.transform.position.x;
			sceneX += Mathf.Floor(sceneX) != sceneX ? 1 : 0;
			float sceneY = wall.transform.position.y;
			sceneY += Mathf.Floor(sceneY) != sceneY ? 1 : 0;
			int x = ((int)sceneX) * 100;
			int y = ((int)sceneY) * 100;
			Texture2D texture = wall.sprite.texture;
			WriteTexture(wallToCreate, texture, x, y);
		}

		wallToCreate.Apply();

		string assetPath = AssetDatabase.GetAssetPath(wallToCreate).Replace("Assets/", "");
		File.WriteAllBytes(Application.dataPath + "/" + assetPath, wallToCreate.EncodeToPNG());
		AssetDatabase.Refresh();
		wallParent.SetActive(false);
	}

	public void CreateTileConnections()
	{
		Tile[] allTiles = tileParent.GetComponentsInChildren<Tile>();
		foreach (Tile tile in allTiles)
		{
			tile.neighbours.Clear();
			tile.FindAllNeighbours();
			tile.neighbourDoors.Clear();
		}

		wallParent.SetActive(true);
		SpriteRenderer[] wallPieces = wallParent.GetComponentsInChildren<SpriteRenderer>();
		wallParent.SetActive(false);
		Tile temp;
		foreach (SpriteRenderer wall in wallPieces)
		{
			if (Mathf.Floor(wall.transform.position.y) != wall.transform.position.y)
			{
				temp = Tile.CastForTile(wall.transform.position + Vector3.up * 0.5f);
				if (temp) temp.down = null;
				temp = Tile.CastForTile(wall.transform.position + Vector3.down * 0.5f);
				if (temp) temp.up = null;
			}
			else
			{
				temp = Tile.CastForTile(wall.transform.position + Vector3.left * 0.5f);
				if (temp) temp.right = null;
				temp = Tile.CastForTile(wall.transform.position + Vector3.right * 0.5f);
				if (temp) temp.left = null;
			}
		}


		Door[] allDoors = doorParent.GetComponentsInChildren<Door>();
		Tile tile1, tile2;
		foreach (Door door in allDoors)
		{
			door.connections.Clear();
			if (door.doorType == Door.DoorType.Left || door.doorType == Door.DoorType.Right)
			{
				if (door.transform.rotation.eulerAngles.z % 180 <= 1)	// 1 is for a margin of error
				{
					tile1 = Tile.CastForTile(door.transform.position + Vector3.left * 0.5f);
					tile2 = Tile.CastForTile(door.transform.position + Vector3.right * 0.5f);
					door.connections.Add(new Door.TileConnection(tile1, tile2));
					
					tile1.neighbourDoors.Add(door);
					tile2.neighbourDoors.Add(door);
				}
				else
				{
					tile1 = Tile.CastForTile(door.transform.position + Vector3.up * 0.5f);
					tile2 = Tile.CastForTile(door.transform.position + Vector3.down * 0.5f);
					door.connections.Add(new Door.TileConnection(tile1, tile2));
					
					tile1.neighbourDoors.Add(door);
					tile2.neighbourDoors.Add(door);
				}
			}
			else
			{
				if (door.transform.rotation.eulerAngles.z % 180 <= 1)	// 1 is for a margin of error
				{
					tile1 = Tile.CastForTile(door.transform.position + Vector3.left * 0.5f + Vector3.up * 0.5f);
					tile2 = Tile.CastForTile(door.transform.position + Vector3.right * 0.5f + Vector3.up * 0.5f);
					door.connections.Add(new Door.TileConnection(tile1, tile2));
					
					tile1.neighbourDoors.Add(door);
					tile2.neighbourDoors.Add(door);
					
					tile1 = Tile.CastForTile(door.transform.position + Vector3.left * 0.5f + Vector3.down * 0.5f);
					tile2 = Tile.CastForTile(door.transform.position + Vector3.right * 0.5f + Vector3.down * 0.5f);
					door.connections.Add(new Door.TileConnection(tile1, tile2));
					
					tile1.neighbourDoors.Add(door);
					tile2.neighbourDoors.Add(door);
				}
				else
				{
					tile1 = Tile.CastForTile(door.transform.position + Vector3.up * 0.5f + Vector3.right * 0.5f);
					tile2 = Tile.CastForTile(door.transform.position + Vector3.down * 0.5f + Vector3.right * 0.5f);
					door.connections.Add(new Door.TileConnection(tile1, tile2));
					
					tile1.neighbourDoors.Add(door);
					tile2.neighbourDoors.Add(door);
					
					tile1 = Tile.CastForTile(door.transform.position + Vector3.up * 0.5f + Vector3.left * 0.5f);
					tile2 = Tile.CastForTile(door.transform.position + Vector3.down * 0.5f + Vector3.left * 0.5f);
					door.connections.Add(new Door.TileConnection(tile1, tile2));
					
					tile1.neighbourDoors.Add(door);
					tile2.neighbourDoors.Add(door);
				}
			}

			EditorUtility.SetDirty(door);
		}

		foreach (Tile tile in allTiles)
		{
			EditorUtility.SetDirty(tile);
		}
	}

	private void ClearTexture(Texture2D _texture)
	{
		for (int i = 0; i < _texture.width; i++)
		{
			for (int j = 0; j < _texture.height; j++)
			{
				_texture.SetPixel(i, j, Color.clear);
			}
		}
	}

	private void WriteTexture(Texture2D _canvas, Texture2D _toAdd, int _x, int _y)
	{
		for (int i = 0; i < _toAdd.width; i++)
		{
			for (int j = 0; j < _toAdd.height; j++)
			{
				if (_toAdd.GetPixel(i, j).a == 1 || _canvas.GetPixel(i + _x, j + _y).a == 0)
				{
					_canvas.SetPixel(i + _x, j + _y, _toAdd.GetPixel(i, j));
				}
			}
		}
	}
}
